package factory

import (
	"sync"

	"github.com/go-viper/mapstructure/v2"
	"go.uber.org/zap"
	"xincan.com.cn/tarot-go/internal/common/constants"
	"xincan.com.cn/tarot-go/internal/common/types"
	"xincan.com.cn/tarot-go/internal/components/logging"
)

// applicationConfigFactoryProvider
// Title    			applicationConfigFactoryProvider
// Description   		定义配置中心工厂结构体
// Author      			alittlexincan@163.com       			2024/07/17 11:36
// Update    			alittlexincan@163.com       			2024/07/17 11:36
type applicationConfigFactoryProvider struct {

	// provider 配置中心类型
	provider constants.ProviderType

	// logger 日志接口
	logger *logging.TraceLogger

	// app 配置信息
	app *types.Service

	// config 创建者, 创建配置中心加载器接口
	config map[constants.ProviderType]RemoteApplicationConfigLoaderFactory

	// registry 创建者, 注册中心加载器接口
	registry map[constants.ProviderType]ApplicationRegistryLoaderFactory

	// cache 创建者, 缓存加载器接口
	cache map[constants.ProviderType]ApplicationCacheLoaderFactory

	// orm 创建者, 对象关系映射加载器接口
	orm map[constants.ProviderType]ApplicationOrmLoaderFactory

	// database 创建者, 数据库加载器接口
	database map[constants.ProviderType]ApplicationDatabaseLoaderFactory

	// mu 读写锁
	mu sync.RWMutex
}

// WithProvider
// Title    			WithProvider
// Description			配置器: 添加配置中心加载器接口
// Author      			alittlexincan@163.com       						2024/07/17 11:36
// Update    			alittlexincan@163.com       						2024/07/17 11:36
// Param    			provider 				enum.ProviderType			配置中心类型
// Return    			*applicationConfigFactoryProvider     		返回配置实例工厂
func (remote *applicationConfigFactoryProvider) WithProvider(provider constants.ProviderType) *applicationConfigFactoryProvider {
	remote.provider = provider
	return remote
}

// WithLogger
// Title    			WithLogger
// Description			配置器: 添加日志接口
// Author      			alittlexincan@163.com       						2024/07/17 11:36
// Update    			alittlexincan@163.com       						2024/07/17 11:36
// Param    			logger 						*logging.TraceLogger 		日志接口
// Return    			*applicationConfigFactoryProvider     		返回配置实例工厂
func (remote *applicationConfigFactoryProvider) WithLogger(logger *logging.TraceLogger) *applicationConfigFactoryProvider {
	remote.logger = logger
	return remote
}

// WithService
// Title    			WithService
// Description			配置器: 添加系统配置信息
// Author      			alittlexincan@163.com       						2024/07/17 11:36
// Update    			alittlexincan@163.com       						2024/07/17 11:36
// Param    			app 						*core.Service			系统配置信息
// Return    			*applicationConfigFactoryProvider     		返回配置实例工厂
func (remote *applicationConfigFactoryProvider) WithService(app *types.Service) *applicationConfigFactoryProvider {
	remote.app = app
	return remote
}

// Build
// Title    			Build
// Description			获取配置中心实例
// Author      			alittlexincan@163.com       											2024/07/17 11:36
// Update    			alittlexincan@163.com       											2024/07/17 11:36
// Param    			provider 						enum.ProviderType						配置中心类型
// Param    			config 							*core.Service							系统配置信息
// Return    			remoteApplicationConfigFactoryProvider     								返回配置实例工厂
func (remote *applicationConfigFactoryProvider) Build() RemoteApplicationConfigLoaderFactory {
	remote.mu.RLock()
	defer remote.mu.RUnlock()
	// 根据配置中心类型, 获取配置实例工厂
	instance, exists := remote.config[remote.provider]
	if !exists {
		remote.logger.Logger.Error("不支持的配置中心类型", zap.Any("provider", remote.provider))
	}
	// 解析配置
	data := remote.app.Config.ConfigCenter.Center[remote.provider.Value()]
	// 解析配置实例工厂
	if err := mapstructure.WeakDecode(data, &instance); err != nil {
		remote.logger.Logger.Error("解析配置中心配置失败", zap.Any("provider", remote.provider), zap.Error(err))
	}
	// 注入自身具体结构体实例, 添加日志接口, 添加配置信息
	instance.SetSelf(instance).WithLogger(remote.logger).WithApplicationConfig(remote.app)
	return instance
}

// InstanceFactory
// Title 				InstanceFactory
// Description 			配置实例工厂
// Author  				alittlexincan@163.com 					2024/07/22 11:36
// Update  				alittlexincan@163.com 					2024/07/22 11:36
var InstanceFactory = &applicationConfigFactoryProvider{
	// 配置中心实例工厂
	config: make(map[constants.ProviderType]RemoteApplicationConfigLoaderFactory),

	// 注册中心实例工厂
	registry: make(map[constants.ProviderType]ApplicationRegistryLoaderFactory),

	// 缓存信息实例工厂
	cache: make(map[constants.ProviderType]ApplicationCacheLoaderFactory),

	// 对象关系映射实例工厂
	orm: make(map[constants.ProviderType]ApplicationOrmLoaderFactory),

	// 数据库实例工厂
	database: make(map[constants.ProviderType]ApplicationDatabaseLoaderFactory),
}

// GetConfigFactory
// Title    			GetConfigFactory
// Description 			获取配置中心实例工厂
// Author      			alittlexincan@163.com       											2024/07/17 11:36
// Update    			alittlexincan@163.com       											2024/07/17 11:36
// Return    			RemoteApplicationConfigLoaderFactory     								返回配置实例工厂
func GetConfigFactory(provider constants.ProviderType) RemoteApplicationConfigLoaderFactory {
	return InstanceFactory.config[provider]
}

// GetRegistryFactory
// Title    			GetRegistryFactory
// Description 			获取注册中心实例工厂
// Author      			alittlexincan@163.com       											2024/07/17 11:36
// Update    			alittlexincan@163.com       											2024/07/17 11:36
// Return    			ApplicationRegistryLoaderFactory     									返回配置实例工厂
func GetRegistryFactory(provider constants.ProviderType) ApplicationRegistryLoaderFactory {
	return InstanceFactory.registry[provider]
}

// GetCacheFactory
// Title    			GetCacheFactory
// Description 			获取缓存实例工厂
// Author      			alittlexincan@163.com       											2024/07/17 11:36
// Update    			alittlexincan@163.com       											2024/07/17 11:36
// Return    			ApplicationRegistryLoaderFactory     									返回配置实例工厂
func GetCacheFactory(provider constants.ProviderType) ApplicationCacheLoaderFactory {
	return InstanceFactory.cache[provider]
}

// GetOrmFactory
// Title    			GetOrmFactory
// Description 			获取对象关系映射实例工厂
// Author      			alittlexincan@163.com       											2024/07/17 11:36
// Update    			alittlexincan@163.com       											2024/07/17 11:36
// Return    			ApplicationOrmLoaderFactory     										返回配置实例工厂
func GetOrmFactory(provider constants.ProviderType) ApplicationOrmLoaderFactory {
	return InstanceFactory.orm[provider]
}

// GetDatabaseFactory
// Title    			GetDatabaseFactory
// Description 			获取数据库实例工厂
// Author      			alittlexincan@163.com       											2024/07/17 11:36
// Update    			alittlexincan@163.com       											2024/07/17 11:36
// Return    			ApplicationDatabaseLoaderFactory     									返回配置实例工厂
func GetDatabaseFactory(provider constants.ProviderType) ApplicationDatabaseLoaderFactory {
	return InstanceFactory.database[provider]
}

////////////////////////////////////// Config ///////////////////////////////////////////

// ConfigCenterFactory
// Title    			ConfigCenterFactory
// Description   		配置中心: 全局注册工厂函数
// Author      			alittlexincan@163.com       											2024/07/17 11:36
// Update    			alittlexincan@163.com       											2024/07/17 11:36
// Param    			provider 						enum.ProviderType						配置中心类型
// Param    			factory 						RemoteApplicationConfigLoaderFactory	加载器接口
func ConfigCenterFactory(provider constants.ProviderType, factory RemoteApplicationConfigLoaderFactory) {
	InstanceFactory.mu.Lock()
	defer InstanceFactory.mu.Unlock()
	if instance, exists := InstanceFactory.config[provider]; exists {
		instance.GetLogger().Info("配置中心类型[ "+provider.Value()+" ]已注册，将被覆盖", zap.Any("provider", provider))
	}
	InstanceFactory.config[provider] = factory
}

////////////////////////////////////// Registry ///////////////////////////////////////////

// RegisterCenterFactory
// Title    			RegisterCenterFactory
// Description   		注册中心: 全局注册工厂函数
// Author      			alittlexincan@163.com       											2024/07/17 11:36
// Update    			alittlexincan@163.com       											2024/07/17 11:36
// Param    			provider 						enum.ProviderType						注册中心类型
// Param    			factory 						ApplicationRegistryLoaderFactory		加载器接口
func RegisterCenterFactory(provider constants.ProviderType, factory ApplicationRegistryLoaderFactory) {
	InstanceFactory.mu.Lock()
	defer InstanceFactory.mu.Unlock()
	if instance, exists := InstanceFactory.registry[provider]; exists {
		instance.GetLogger().Info("注册中心类型[ "+provider.Value()+" ]已注册，将被覆盖", zap.Any("provider", provider))
	}
	InstanceFactory.registry[provider] = factory
}

////////////////////////////////////// Cache ///////////////////////////////////////////

// CacheCenterFactory
// Title    			CacheCenterFactory
// Description   		缓存: 全局注册工厂函数
// Author      			alittlexincan@163.com       											2024/07/17 11:36
// Update    			alittlexincan@163.com       											2024/07/17 11:36
// Param    			provider 						enum.ProviderType						缓存信息类型
// Param    			factory 						ApplicationCacheLoaderFactory			加载器接口
func CacheCenterFactory(provider constants.ProviderType, factory ApplicationCacheLoaderFactory) {
	InstanceFactory.mu.Lock()
	defer InstanceFactory.mu.Unlock()
	if instance, exists := InstanceFactory.cache[provider]; exists {
		instance.GetLogger().Info("缓存信息类型[ "+provider.Value()+" ]已注册，将被覆盖", zap.Any("provider", provider))

	}
	InstanceFactory.cache[provider] = factory
}

////////////////////////////////////// Orm ///////////////////////////////////////////

// OrmCenterFactory
// Title    			OrmCenterFactory
// Description   		对象关系映射: 全局注册工厂函数
// Author      			alittlexincan@163.com       											2024/07/17 11:36
// Update    			alittlexincan@163.com       											2024/07/17 11:36
// Param    			provider 						enum.ProviderType						缓存信息类型
// Param    			factory 						ApplicationOrmLoaderFactory				加载器接口
func OrmCenterFactory(provider constants.ProviderType, factory ApplicationOrmLoaderFactory) {
	InstanceFactory.mu.Lock()
	defer InstanceFactory.mu.Unlock()
	if instance, exists := InstanceFactory.orm[provider]; exists {
		instance.GetLogger().Info("数据存储类型[ "+provider.Value()+" ]已注册，将被覆盖", zap.Any("provider", provider))
	}
	InstanceFactory.orm[provider] = factory
}

////////////////////////////////////// Database ///////////////////////////////////////////

// DatabaseCenterFactory
// Title    			DatabaseCenterFactory
// Description   		数据库: 全局注册工厂函数
// Author      			alittlexincan@163.com       											2024/07/17 11:36
// Update    			alittlexincan@163.com       											2024/07/17 11:36
// Param    			provider 						enum.ProviderType						缓存信息类型
// Param    			factory 						ApplicationDatabaseLoaderFactory		加载器接口
func DatabaseCenterFactory(provider constants.ProviderType, factory ApplicationDatabaseLoaderFactory) {
	InstanceFactory.mu.Lock()
	defer InstanceFactory.mu.Unlock()
	if instance, exists := InstanceFactory.database[provider]; exists {
		instance.GetLogger().Info("数据存储类型[ "+provider.Value()+" ]已注册，将被覆盖", zap.Any("provider", provider))
	}
	InstanceFactory.database[provider] = factory
}
